﻿using System;
using System.Drawing;
using System.Collections.Generic;

namespace BullsEyeGame
{
    /// <summary>
    /// A class responsable for the two ways translation of colors to letters and letters to colors
    /// in order to work with the letters of the logical game while presenting colors to the user
    /// </summary>
    internal class LettersColorsTranlator
    {
        private static LettersColorsTranlator s_Instance = null;
        private List<string> m_AllColorNames;
        private List<KnownColor> m_GuessColors = null;
        private Dictionary<Guess.eGuessLetters, KnownColor> m_LettersToColors = new Dictionary<Guess.eGuessLetters, KnownColor>();
        private Dictionary<KnownColor, Guess.eGuessLetters> m_ColorsToLetters = new Dictionary<KnownColor, Guess.eGuessLetters>();

        private LettersColorsTranlator()
        {
            initializeDictionary();
        }

        /// <summary>
        /// Will return the instance of this single-ton class
        /// </summary>
        public static LettersColorsTranlator Instance
        {
            get
            {
                if (s_Instance == null)
                {
                    s_Instance = new LettersColorsTranlator();
                }

                return s_Instance;
            }
        }

        /// <summary>
        /// Property to get all the guess colors available
        /// </summary>
        public List<KnownColor> GuessColors
        {
            get
            {
                if (m_GuessColors == null)
                {
                    m_GuessColors = getAllGuessColors();
                }

                return m_GuessColors;
            }
        }

        /// <summary>
        /// Will translate a guess letter to a color
        /// </summary>
        /// <param name="i_GuessLetter">The guess letter to be translated</param>
        /// <returns>The translated color in the form of KnownColor</returns>
        public KnownColor TranslateLetterToColor(Guess.eGuessLetters i_GuessLetter)
        {
            KnownColor guessColorResult;
            m_LettersToColors.TryGetValue(i_GuessLetter, out guessColorResult);

            return guessColorResult;
        }

        /// <summary>
        /// Will translate a color to a guess letter
        /// </summary>
        /// <param name="i_GuessColor">The color in the form of KnownColor to be translated</param>
        /// <returns>The translated guess letter </returns>
        public Guess.eGuessLetters TranslateColorToLetter(KnownColor i_GuessColor)
        {
            Guess.eGuessLetters guessLetterResult;
            m_ColorsToLetters.TryGetValue(i_GuessColor, out guessLetterResult);

            return guessLetterResult;
        }

        /// <summary>
        /// Will translate a name of a guess letter to a color
        /// </summary>
        /// <param name="i_LetterName">The guess letter name to be translated</param>
        /// <returns>The translated color in the form of KnownColor</returns>
        public KnownColor TranslateLetterNameToColor(string i_LetterName)
        {
            Guess.eGuessLetters letter = (Guess.eGuessLetters)Enum.Parse(typeof(Guess.eGuessLetters), i_LetterName);
            return TranslateLetterToColor(letter);
        }

        /// <summary>
        /// Will translate a color name to a guess letter
        /// </summary>
        /// <param name="i_ColorName">The color name to be translated</param>
        /// <returns>The translated guess letter </returns>
        public Guess.eGuessLetters TranslateColorNameToLetter(string i_ColorName)
        {
            KnownColor color = (KnownColor) Enum.Parse(typeof(KnownColor), i_ColorName);
            return TranslateColorToLetter(color);
        }

        /// <summary>
        /// Will translate a list of guess letters to a list of colors
        /// </summary>
        /// <param name="i_Letters">The guess letters to be translated</param>
        /// <returns>The translated colors in the form of KnownColor</returns>
        public List<KnownColor> TranslateLettersToColors(List<Guess.eGuessLetters> i_Letters)
        {
            List<KnownColor> translatedColors = new List<KnownColor>();
            KnownColor translatedColor;
            foreach (Guess.eGuessLetters currentLetter in i_Letters)
            {
                translatedColor = TranslateLetterToColor(currentLetter);
                translatedColors.Add(translatedColor);
            }

            return translatedColors;
        }

        /// <summary>
        /// Will translate a list of colors to a list of guess letters
        /// </summary>
        /// <param name="i_Colors">The colors in the form of KnownColor to be translated</param>
        /// <returns>The translated guess letters </returns>
        public List<Guess.eGuessLetters> TranslateColorsToLetters(List<KnownColor> i_Colors)
        {
            List<Guess.eGuessLetters> translatedLetters = new List<Guess.eGuessLetters>();
            Guess.eGuessLetters translatedLetter;
            foreach (KnownColor currentColor in i_Colors)
            {
                translatedLetter = TranslateColorToLetter(currentColor);
                translatedLetters.Add(translatedLetter);
            }

            return translatedLetters;
        }

        /// <summary>
        /// Creates a list of colors in the form of KnownColor from the input list of colors 
        /// </summary>
        /// <param name="i_ColorsToChange">The colors list from which to create the colors list in the form of known color</param>
        /// <returns>The corresponding colors list in the form of KnownColor</returns>
        public List<KnownColor> ColorsToKnowColors(List<Color> i_ColorsToChange)
        {
            List<KnownColor> result = new List<KnownColor>();

            foreach (Color currentColor in i_ColorsToChange)
            {
                result.Add(currentColor.ToKnownColor());
            }

            return result;
        }

        private static KnownColor getColorEnumByName(string i_ColorName)
        {
            return (KnownColor)Enum.Parse(typeof(KnownColor), i_ColorName, true);
        }

        private static List<string> getAllColorsNames()
        {
            List<string> colors = new List<string>(9);

            colors.Add("Khaki");
            colors.Add("Red"); 
            colors.Add("Blue");
            colors.Add("Salmon");
            colors.Add("Green");
            colors.Add("Orange");
            colors.Add("Purple");
            colors.Add("SaddleBrown");
            colors.Add("Teal");

            return colors;
        }

        private void initializeDictionary()
        {
            string CurrentColorName;
            int currentColorIndex = 0;
            KnownColor guessColor;

            foreach (Guess.eGuessLetters guessLetter in Enum.GetValues(typeof(Guess.eGuessLetters)))
            {
                CurrentColorName = getColorNameByIndex(currentColorIndex);
                guessColor = getColorEnumByName(CurrentColorName);
                m_LettersToColors.Add(guessLetter, guessColor);
                m_ColorsToLetters.Add(guessColor, guessLetter);
                ++currentColorIndex;
            }
        }

        private string getColorNameByIndex(int i_ColorIndex)
        {
            if (m_AllColorNames == null)
            {
                m_AllColorNames = getAllColorsNames();
            }

            return m_AllColorNames[i_ColorIndex];
        }

        private List<KnownColor> getAllGuessColors()
        {
            List<KnownColor> result = new List<KnownColor>();
            
            foreach (KeyValuePair<KnownColor, Guess.eGuessLetters> keyValuePair in m_ColorsToLetters)
            {
                result.Add(keyValuePair.Key);
            }

            return result;
        }                
    }
}
